#ifndef __SETTINGS__
#include <iostream>
#include <gmpxx.h>
#include <vector>
#include <map>
#include <string>

// some error messages might be thrown out
#define INCOMPATIBLE_RINGS "incompatible polynomial rings"
#define INCOMPATIBLE_POLYS "incompatible polynomial type"
#define NOT_IMPLEMENTED "not implemented yet"

namespace RealPoly{
	using std::pair;
	using std::cout;	
	using std::endl;
	using std::vector;
	using std::string;
	
	//! type of exponent or degree in RealPoly
	typedef size_t Exponent; 
	typedef mpz_class Integer; 
	typedef mpq_class Rational; 
}

#define __SETTINGS__
#endif


#ifndef COCOA_SETTINGS
#include <sstream>
#include <map>
#include "CoCoA/library.H"

namespace RealPoly{
		
	using std::map;

	using CoCoA::SparsePolyRing;
	using CoCoA::ConstRefRingElem;
	using CoCoA::RingElem;
	using CoCoA::RefRingElem;
	using CoCoA::symbol;
	using CoCoA::PolyRing;


	typedef  CoCoA::RingElem CoCoA_Polynomial;

	typedef long CoCoAExponent;

	CoCoA::ZZ  integer2zz(const Integer& );

	class PolynomialRing; //forward declaration

}

#define COCOA_SETTINGS
#endif



#ifndef _INTERFACE_WRAPPER_

namespace RealPoly{


//! the type of a polynomial ring		
class PolynomialRing {

public:
	//! copy ctor
	PolynomialRing(const PolynomialRing& ri) : __variables(ri.__variables), __characteristic(ri.__characteristic),__id(ri.__id) {
	}

	//! assignment
	PolynomialRing operator=(const PolynomialRing& ri) {
		return PolynomialRing(ri);
	}

	//! the real ctor
	PolynomialRing(const vector<string>& vars,  const Integer& ch=Integer(0));

	//! test whether or not two PolynomialRing are equal
	bool operator==(const PolynomialRing& r2) {
		return (__id == r2.__id);
	}

private:
	
	//! strings of variables
	const vector<string> __variables;

	//! characteristic of the ring
	const Integer __characteristic;

	//! id of the ring
	size_t __id;

	
	static size_t __id_counter;

	friend pair< CoCoA::ring, vector<CoCoA::symbol> > CoCoA_Parser(size_t);
	friend class Polynomial;
};


//! the types to wrap
enum PolynomialType { COCOA, BPAS, SDMP };


//! a wrapper for all different implementation of polynomials
/*! provide common interface*/
class Polynomial {
		public:

				/* constructors */

				//! zero constructor
				Polynomial(const PolynomialRing& R, PolynomialType flag=COCOA);

				//! destructor
				~Polynomial();


					
		private:
				//! a flag indicating implementation details of 
				// the polynomial data
				PolynomialType __flag; // indicating implementation detail
				
				//! the actually data for a polynomial
				void* __data;  // the true data, has to be retrived by type indicator

				//! convert data from different representations
				const Polynomial& __convert(PolynomialType flag);

				//! the polynomial ring: dangerous
				// check if two polynomial are compatible for certain operations
				// ring has to be alive ...  howto ensure this?
				// universal symbolic ring: ring contains all variables in the 
				// running environment
				// const PolynomialRing& __ring;
				size_t __ring; // the id of the ring

				//! all rings
				static vector<PolynomialRing> __rings;

};


}

#define _INTERFACE_WRAPPER_
#endif
